home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 7: Sunsite / Linux Cubed Series 7 - Sunsite Vol 1.iso / system / network / manageme / tcpdump-.001 / tcpdump-~ / tcpdump-3.0.2-linux / libpcap-0.0.6 / pcap-nit.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-02-11  |  5.5 KB  |  241 lines

  1. /*
  2.  * Copyright (c) 1990, 1991, 1992, 1993, 1994
  3.  *    The Regents of the University of California.  All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms, with or without
  6.  * modification, are permitted provided that: (1) source code distributions
  7.  * retain the above copyright notice and this paragraph in its entirety, (2)
  8.  * distributions including binary code include the above copyright notice and
  9.  * this paragraph in its entirety in the documentation or other materials
  10.  * provided with the distribution, and (3) all advertising materials mentioning
  11.  * features or use of this software display the following acknowledgement:
  12.  * ``This product includes software developed by the University of California,
  13.  * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
  14.  * the University nor the names of its contributors may be used to endorse
  15.  * or promote products derived from this software without specific prior
  16.  * written permission.
  17.  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
  18.  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
  19.  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  20.  */
  21. #ifndef lint
  22. static  char rcsid[] =
  23.     "@(#)$Header: pcap-nit.c,v 1.24 94/02/10 23:02:37 leres Exp $ (LBL)";
  24. #endif
  25.  
  26. #include <sys/types.h>
  27. #include <sys/time.h>
  28. #include <sys/timeb.h>
  29. #include <sys/file.h>
  30. #include <sys/ioctl.h>
  31. #include <sys/socket.h>
  32.  
  33. #include <net/bpf.h>
  34. #include <net/if.h>
  35. #include <net/nit.h>
  36.  
  37. #include <netinet/in.h>
  38. #include <netinet/in_systm.h>
  39. #include <netinet/ip.h>
  40. #include <netinet/if_ether.h>
  41. #include <netinet/ip_var.h>
  42. #include <netinet/udp.h>
  43. #include <netinet/udp_var.h>
  44. #include <netinet/tcp.h>
  45. #include <netinet/tcpip.h>
  46.  
  47. #include <ctype.h>
  48. #include <errno.h>
  49. #include <stdio.h>
  50.  
  51. #include "pcap-int.h"
  52.  
  53. /*
  54.  * The chunk size for NIT.  This is the amount of buffering
  55.  * done for read calls.
  56.  */
  57. #define CHUNKSIZE (2*1024)
  58.  
  59. /*
  60.  * The total buffer space used by NIT.
  61.  */
  62. #define BUFSPACE (4*CHUNKSIZE)
  63.  
  64. /* Forwards */
  65. static int nit_setflags(int, int, int, char *);
  66.  
  67. int
  68. pcap_stats(pcap_t *p, struct pcap_stat *ps)
  69. {
  70.  
  71.     *ps = p->md.stat;
  72.     return (0);
  73. }
  74.  
  75. int
  76. pcap_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
  77. {
  78.     register int cc, n;
  79.     register struct bpf_insn *fcode = p->fcode.bf_insns;
  80.     register u_char *bp, *cp, *ep;
  81.     register struct nit_hdr *nh;
  82.     register int caplen;
  83.  
  84.     cc = p->cc;
  85.     if (cc == 0) {
  86.         cc = read(p->fd, (char *)p->buffer, p->bufsize);
  87.         if (cc < 0) {
  88.             if (errno == EWOULDBLOCK)
  89.                 return (0);
  90.             sprintf(p->errbuf, "pcap_read: %s",
  91.                 pcap_strerror(errno));
  92.             return (-1);
  93.         }
  94.         bp = p->buffer;
  95.     } else
  96.         bp = p->bp;
  97.  
  98.     /*
  99.      * Loop through each packet.  The increment expression
  100.      * rounds up to the next int boundary past the end of
  101.      * the previous packet.
  102.      */
  103.     n = 0;
  104.     ep = bp + cc;
  105.     while (bp < ep) {
  106.         nh = (struct nit_hdr *)bp;
  107.         cp = bp + sizeof(*nh);
  108.  
  109.         switch (nh->nh_state) {
  110.  
  111.         case NIT_CATCH:
  112.             break;
  113.  
  114.         case NIT_NOMBUF:
  115.         case NIT_NOCLUSTER:
  116.         case NIT_NOSPACE:
  117.             p->md.stat.ps_drop = nh->nh_dropped;
  118.             continue;
  119.  
  120.         case NIT_SEQNO:
  121.             continue;
  122.  
  123.         default:
  124.             sprintf(p->errbuf, "bad nit state %d", nh->nh_state);
  125.             return (-1);
  126.         }
  127.         ++p->md.stat.ps_recv;
  128.         bp += ((sizeof(struct nit_hdr) + nh->nh_datalen +
  129.             sizeof(int) - 1) & ~(sizeof(int) - 1));
  130.  
  131.         caplen = nh->nh_wirelen;
  132.         if (caplen > p->snapshot)
  133.             caplen = p->snapshot;
  134.         if (bpf_filter(fcode, cp, nh->nh_wirelen, caplen)) {
  135.             struct pcap_pkthdr h;
  136.             h.ts = nh->nh_timestamp;
  137.             h.len = nh->nh_wirelen;
  138.             h.caplen = caplen;
  139.             (*callback)(user, &h, cp);
  140.             if (++n >= cnt && cnt >= 0) {
  141.                 p->cc = ep - bp;
  142.                 p->bp = bp;
  143.                 return (n);
  144.             }
  145.         }
  146.     }
  147.     p->cc = 0;
  148.     return (n);
  149. }
  150.  
  151. static int
  152. nit_setflags(int fd, int promisc, int to_ms, char *ebuf)
  153. {
  154.     struct nit_ioc nioc;
  155.  
  156.     bzero((char *)&nioc, sizeof(nioc));
  157.     nioc.nioc_bufspace = BUFSPACE;
  158.     nioc.nioc_chunksize = CHUNKSIZE;
  159.     nioc.nioc_typetomatch = NT_ALLTYPES;
  160.     nioc.nioc_snaplen = p->snapshot;
  161.     nioc.nioc_bufalign = sizeof(int);
  162.     nioc.nioc_bufoffset = 0;
  163.  
  164.     if (to_ms != 0) {
  165.         nioc.nioc_flags |= NF_TIMEOUT;
  166.         nioc.nioc_timeout.tv_sec = to_ms / 1000;
  167.         nioc.nioc_timeout.tv_usec = (to_ms * 1000) % 1000000;
  168.     }
  169.     if (promisc)
  170.         nioc.nioc_flags |= NF_PROMISC;
  171.  
  172.     if (ioctl(fd, SIOCSNIT, &nioc) < 0) {
  173.         sprintf(ebuf, "SIOCSNIT: %s", pcap_strerror(errno));
  174.         return (-1);
  175.     }
  176.     return (0);
  177. }
  178.  
  179. pcap_t *
  180. pcap_open_live(char *device, int snaplen, int promisc, int to_ms, char *ebuf)
  181. {
  182.     int fd;
  183.     struct sockaddr_nit snit;
  184.     register pcap_t *p;
  185.  
  186.     p = (pcap_t *)malloc(sizeof(*p));
  187.     if (p == NULL) {
  188.         strcpy(ebuf, pcap_strerror(errno));
  189.         return (NULL);
  190.     }
  191.  
  192.     if (snaplen < 96)
  193.         /*
  194.          * NIT requires a snapshot length of at least 96.
  195.          */
  196.         snaplen = 96;
  197.  
  198.     bzero(p, sizeof(*p));
  199.     p->fd = fd = socket(AF_NIT, SOCK_RAW, NITPROTO_RAW);
  200.     if (fd < 0) {
  201.         sprintf(ebuf, "socket: %s", pcap_strerror(errno));
  202.         goto bad;
  203.     }
  204.     snit.snit_family = AF_NIT;
  205.     (void)strncpy(snit.snit_ifname, device, NITIFSIZ);
  206.  
  207.     if (bind(fd, (struct sockaddr *)&snit, sizeof(snit))) {
  208.         sprintf(ebuf, "bind: %s: %s", snit.snit_ifname,
  209.             pcap_strerror(errno));
  210.         goto bad;
  211.     }
  212.     p->snapshot = snaplen;
  213.     nit_setflags(p->fd, promisc, to_ms, ebuf);
  214.  
  215.     /*
  216.      * NIT supports only ethernets.
  217.      */
  218.     p->linktype = DLT_EN10MB;
  219.  
  220.     p->bufsize = BUFSPACE;
  221.     p->buffer = (u_char *)malloc(p->bufsize);
  222.     if (p->buffer == NULL) {
  223.         strcpy(ebuf, pcap_strerror(errno));
  224.         goto bad;
  225.     }
  226.     return (p);
  227.  bad:
  228.     if (fd >= 0)
  229.         close(fd);
  230.     free(p);
  231.     return (NULL);
  232. }
  233.  
  234. int
  235. pcap_setfilter(pcap_t *p, struct bpf_program *fp)
  236. {
  237.  
  238.     p->fcode = *fp;
  239.     return (0);
  240. }
  241.